/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Generic Collection Base C;ass
 *      Provides a base implementation for creating generics-based strongly-
 * typed collection classes.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "StdAfx.h"
#include "GenericCollectionBase.h"

using namespace System;
using namespace System::Collections;
using namespace System::Collections::Generic;

namespace Adaptive
{
	namespace Foundation
	{
        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
#pragma region Constructor / Dispose / Destructor Methods
		// Initializes a new instance of the class.
		generic<typename T>
		GenericCollectionBase<T>::GenericCollectionBase()
		{
			_keyList = nullptr;
			_storage = nullptr;
			_currentIndex = -1;

			_storage = gcnew List<T>();
			_keyList = gcnew Dictionary<String^, int>();

		}
		// Deallocates internal memory usage.
		generic<typename T>
		GenericCollectionBase<T>::~GenericCollectionBase()
		{
			if (!Disposed)
			{
				if (_storage != nullptr)
					delete(_storage);

				if (_keyList != nullptr)
					delete(_keyList);
			}
			_storage = nullptr;
			_keyList = nullptr;
		}
		generic<typename T>
		GenericCollectionBase<T>::!GenericCollectionBase()
		{
			_storage = nullptr;
			_keyList = nullptr;
		}

#pragma endregion

		/*--------------------------------------------------------------------------------
		 * Public Properties
		 *------------------------------------------------------------------------------*/
#pragma region Public Properties
		// Gets the number of items currently stored in the collection.
		generic<typename T>
		int GenericCollectionBase<T>::Count::get()
		{
			return _storage->Count;
		}
		// Gets the item at the specified index from the collection.
		generic<typename T>
		T GenericCollectionBase<T>::default::get(int index)
		{
			if ((index >= 0) && (index < Count))
				return _storage[index];
			else
				return T();
		}
		// Gets the item with the specified reference key from the collection.
		generic<typename T>
		T GenericCollectionBase<T>::default::get(String^ referenceKey)
		{
			int index = -1;

			if (_keyList->ContainsKey(referenceKey))
			{
				index = _keyList[referenceKey];
				return this[index];
			}
			else
				return T();
		}
		
		// Gets a value indicating whether the local enumeration has reached the
		generic<typename T>
		bool GenericCollectionBase<T>::Eof::get()
		{
			return (_currentIndex < 0) || (_currentIndex >= Count);
		}
		// Gets a value indicating whether the collection instance is a 
		generic<typename T>
		bool GenericCollectionBase<T>::IsReadOnly::get()
		{
			return false;
		}
		// Gets a value indicating whether the local enumeration has reached the
		// item next to the end of the collection contents.
		generic<typename T>
		bool GenericCollectionBase<T>::NextToLast::get()
		{
			return (_currentIndex == Count - 1);
		}
		// Gets the reference to the object instance at the current position in the 
		// local collection enumeration.
		generic<typename T>
		T GenericCollectionBase<T>::Value::get()
		{
                if (!Eof)
                    return _storage[_currentIndex];
                else
                    return T();
		}
#pragma endregion

		/*--------------------------------------------------------------------------------
		 * Public Methods / Functions
		 *------------------------------------------------------------------------------*/
#pragma region Public Methods / Functions
		// Appends a new object instance to the collection.
		generic<typename T>
		void GenericCollectionBase<T>::Add(T itemToBeAdded)
		{
			String^ keyValue = String::Empty;     //Key value.

            if (itemToBeAdded != nullptr)
            {
                //Get the key value.
                keyValue = GetKeyForObject(itemToBeAdded);

				if (!(_keyList->ContainsKey(keyValue)))
				{
					//Store the item in the storage list.
					_storage->Add(itemToBeAdded);
					//Store the key-and-index pair.
					_keyList->Add(keyValue, _storage->Count - 1);
				}
            }
		}
		// Removes the contents of the collection.
		generic<typename T>
		void GenericCollectionBase<T>::Clear()
		{
            if (_storage != nullptr)
                _storage->Clear();
            if (_keyList != nullptr)
                _keyList->Clear();
		}
		// Removes all objects from the collection and calls the <b>Dispose</b> method
		// on any <see cref="IDisposable"/> instances in the collection.
		generic<typename T>
		void GenericCollectionBase<T>::ClearAndDispose()
		{
			System::Object^ itemPtr = nullptr;

            //Clear the key list.
            if (_keyList != nullptr)
                _keyList->Clear();

            if (_storage != nullptr)
            {
                //Clear the storage.
                while (_storage->Count > 0)
                {
					itemPtr = (Object^)_storage[0];
					if (dynamic_cast<System::IDisposable^>(itemPtr))
						delete(itemPtr);

                    _storage->RemoveAt(0);
                }
                _storage->Clear();
            }
		}
		// Explicit interface implementation.
		generic<typename T>
		System::Collections::IEnumerator^ GenericCollectionBase<T>::GetNonGenericEnumerator() 
		{
			return gcnew GenericCollectionBaseEnumerator<T>(this);
		}
		// Gets an enumerator for the collection.  To be overidden in descendant classes.
		generic<typename T>
		System::Collections::Generic::IEnumerator<T>^ GenericCollectionBase<T>::GetEnumerator() 
		{
			return gcnew GenericCollectionBaseEnumerator<T>(this);
		}
		// Gets a value indicating whether the specified instance is already present
		// in the collection.
		generic<typename T>
		bool GenericCollectionBase<T>::Contains(T itemToFind)
		{
			return _storage->Contains(itemToFind);
		}
		// Copies the contents of the collection to the specified  array instance.
		generic<typename T>
		void GenericCollectionBase<T>::CopyTo(array<T,1>^ arrayDestination, int startPosition)
		{
            if ((arrayDestination != nullptr) && (arrayDestination->Length >= (Count + startPosition)))
            {
                _storage->CopyTo(arrayDestination, startPosition);
            }
		}
		// Moves the local enumeration pointer to the first item in the collection.
		generic<typename T>
		void GenericCollectionBase<T>::MoveFirst()
		{
            _currentIndex = 0;
            if (Count == 0)
                _currentIndex = -1;
		}
		// Moves the local enumeration pointer to the last item in the collection.
		generic<typename T>
		void GenericCollectionBase<T>::MoveLast()
		{
            _currentIndex = Count - 1;
		}
		// Moves the local enumeration pointer to the next item in the collection.
		generic<typename T>
		void GenericCollectionBase<T>::MoveNext()
		{
            _currentIndex++;
            if (_currentIndex > Count)
                _currentIndex = Count;
            if (Count == 0)
                _currentIndex = -1;
		}
		// Moves the local enumeration pointer to the previous item in the collection.
		generic<typename T>
		void GenericCollectionBase<T>::MovePrevious()
		{
            _currentIndex--;
            if (_currentIndex < 0)
                _currentIndex = 0;
            if (Count == 0)
                _currentIndex = -1;
		}
		// Removes the item at the specified index from the collection.
		generic<typename T>
		void GenericCollectionBase<T>::Remove(int index)
		{
            if ((index >= 0) && (index < Count))
            {
                //Remove object.
                _storage->RemoveAt(index);

                //Re-order keys.
                ReorderKeys();
            }
		}
		// Removes the item with the specified reference key from the collection.
		generic<typename T>
		void GenericCollectionBase<T>::Remove(String^ referenceKey)
		{
            int itemIndex = 0;          //Item index.

            //Get the index.
            if (_keyList->ContainsKey(referenceKey))
                itemIndex = _keyList[referenceKey];
            else
                itemIndex = -1;
            Remove(itemIndex);
		}
		// Removes the specified object from the collection.
		generic<typename T>
		bool GenericCollectionBase<T>::Remove(T itemToBeRemoved)
		{
            bool returnValue = false;           //Return value.

            returnValue = _storage->Contains(itemToBeRemoved);
            if (returnValue)
            {
                Remove(_storage->IndexOf(itemToBeRemoved));
            }
            return returnValue;
		}
#pragma endregion

		/*--------------------------------------------------------------------------------
		 * Private Methods
		 *------------------------------------------------------------------------------*/
#pragma region Private Methods
		// Re-sets the key-and-index list.
		generic<typename T>
		void GenericCollectionBase<T>::ReorderKeys()
		{
			String^ keyValue = String::Empty;         //New key value.
            int count = 0;                          //Iteration counter.
            int length = 0;                         //Iteration limit.

            _keyList->Clear();
            length = _storage->Count;
            for (count = 0; count < length; count++)
            {
                keyValue = GetKeyForObject(_storage[count]);
                _keyList->Add(keyValue, count);
            }
		}
#pragma endregion

	}
}